use crate::tool::Tool;
use tool_macro::tool;
use serde_json::{json, Value};
use anyhow::{Context, Result};
use async_trait::async_trait;
use std::process::Command;

#[tool(
    struct_name = CommandExecutor,
    name = "cmd_executor",
    description = "Execute command in the terminal, and return execute result!",
    args = [
        "command" : {
            "type": "string",
            "description": "The command to execute.",
        }
    ]
)]
pub fn execute_command(command: &str) -> String {
    match Command::new("sh")
        .arg("-c")
        .arg(command)
        .output() {
        Ok(output) => {
            if output.status.success() {
                format!("Execute command with stdout: {}", String::from_utf8_lossy(&output.stdout).to_string())
            } else {
                format!("Execute command with stderr: {}", String::from_utf8_lossy(&output.stderr).to_string())
            }
        }
        Err(err) => {
            format!("Failed to execute command because of {}", err.to_string())
        }
    }
}

#[allow(unused)]
#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_ls() {
        let res = CommandExecutor::execute_command("ls -a");
        print!("{}", res);
    }


    #[test]
    fn test_create_file() {
        let res = CommandExecutor::execute_command("echo 'module counter(input clk, input reset, output reg [3:0] count);\n  always @(posedge clk or posedge reset) begin\n    if (reset) count <= 4\\'b0000;\n    else count <= count + 1;\n  end\nendmodule' > counter.v");
        print!("{}", res);
    }
}